<template>
    <BaseECharts ref="echartRef" height="652px"></BaseECharts>
</template>

<script setup lang="ts">
import { ECOption } from '@/components/baseECharts/config'
import { BaseEchartsType } from '@/components/baseECharts/type'
import { ElMessage } from 'element-plus'

interface MapData {
    adcode: number
    name: string
    level: string
}
// map列表，用于制作面包屑
const mapList = ref<MapData[]>([])
const echartRef = ref<BaseEchartsType>()
// 飞机
const planePath =
    'path://M1705.06,1318.313v-89.254l-319.9-221.799l0.073-208.063c0.521-84.662-26.629-121.796-63.961-121.491c-37.332-0.305-64.482,36.829-63.961,121.491l0.073,208.063l-319.9,221.799v89.254l330.343-157.288l12.238,241.308l-134.449,92.931l0.531,42.034l175.125-42.917l175.125,42.917l0.531-42.034l-134.449-92.931l12.238-241.308L1705.06,1318.313z'

onMounted(() => {
    initECharts()
    clickMapHandle()
})

// 初始化
const initECharts = () => {
    if (echartRef.value) {
        // 初始化新实例
        echartRef.value.init()
        getMapJson(100000, (data) => {
            mapList.value.push({ adcode: 100000, name: '中国', level: 'country' })
            renderECharts('中国', data)
        })
    }
}

// 绑定地图点击事件
const clickMapHandle = () => {
    // 图表实例
    const echartsInstance = echartRef.value?.getEChartsInstance()
    echartsInstance?.on('click', (params: any) => {
        if (params.data) {
            const { adcode, name, level } = params.data
            if (level === 'district') {
                ElMessage.success('不支持继续下钻了哦！')
                return
            } else if (mapList.value.find((item) => item.adcode === adcode)) {
                return
            }
            getMapJson(adcode, (data) => {
                mapList.value.push({ adcode, name, level })
                renderECharts(name, data)
            })
        }
    })
    // echartsInstance?.on('geoRoam', (params: any) => {
    //     const option = echartsInstance.getOption()
    //     const geo = option.geo as any
    //     if (params.zoom != null && params.zoom != undefined) {
    //         //捕捉到缩放时
    //         geo[1].zoom = geo[0].zoom //下层geo的缩放等级跟着上层的geo一起改变
    //         geo[1].center = geo[0].center //下层的geo的中心位置随着上层geo一起改变
    //     } else {
    //         //捕捉到拖曳时
    //         geo[1].center = geo[0].center //下层的geo的中心位置随着上层geo一起改变
    //     }
    //     echartsInstance.setOption(option, false)
    // })
}

// 绑定面包屑点击事件
const clickBreadcrumbsHandle = (name: string, adcode: number) => {
    const currentMapIndex = mapList.value.findIndex((map) => adcode === map.adcode)
    if (currentMapIndex === mapList.value.length - 1) {
        return
    }
    getMapJson(adcode, (data) => {
        mapList.value = mapList.value.filter((map) => map.adcode <= adcode)
        renderECharts(name, data)
    })
}
// 通过阿里云api获得地图数据
const getMapJson = (adcode: number, callback: (data: any) => void) => {
    const url = `https://geo.datav.aliyun.com/areas_v3/bound/${adcode}_full.json`
    fetch(url)
        .then((response) => response.json())
        .then((data) => callback(data))
        .catch((reason) => {
            ElMessage.success(`出错啦：${reason}`)
        })
}

// 渲染地图
const renderECharts = (name: string, data: any) => {
    // 注册地图
    echartRef.value?.registerMap(name, data)
    // 根据 json 数据拼装 mapdata， 用于地图点击下钻时传递数据，主要有adcode、name
    const mapdata = data.features.map((item: any) => item.properties)
    // 配置option
    setOption(name, mapdata)
}

// 随机获取城市坐标点
const getRandomPointData = (mapdata: any) => {
    const data: any[] = []
    generateUniqueArray(6, 0, mapdata.length - 1).forEach((item: any) => {
        const randomMap = mapdata[item]
        if (randomMap && randomMap.name !== '') {
            data.push({ name: randomMap.name, value: randomMap.center })
        }
    })
    return data
}

// 随机生成飞机航线
const getRandomLineData = (mapdata: any) => {
    const data: any[] = []
    const anhui = [117.226884, 31.849254]
    generateUniqueArray(10, 0, mapdata.length - 1).forEach((item: any) => {
        const randomMap = mapdata[item]
        if (randomMap && randomMap.name !== '安徽' && randomMap.name !== '') {
            data.push({ name: randomMap.name, coords: [anhui, randomMap.center] })
        }
    })
    return data
}
// 随机改变五个地区颜色
const getRandomRegionsData = (mapdata: any) => {
    const data: any[] = []
    generateUniqueArray(5, 0, mapdata.length - 1).forEach((item: any) => {
        const randomMap = mapdata[item]
        if (randomMap) {
            const randomColor = getRandomColor()
            data.push({ name: randomMap.name, itemStyle: { areaColor: randomColor } })
        }
    })
    return data
}
// 设置配置
const setOption = (name: string, mapdata: any) => {
    const option: ECOption = {
        graphic: (() => {
            const group: { type: string; children: any[] }[] = []
            // 每个标题前面字符总数的数组 例如：'中国 》 安徽省 》 合肥市' 就是第一项前面0个字符长度，第二项两个字符长度，第三项前面五个字符长度
            const frontCharLengthArr: number[] = []
            // 线宽
            const lineWidth = 1
            // 行高
            const lineHeight = 39
            const fontSize = 18
            const iconWidth = 20
            const titleLeftRigthPadding = 10
            // 位置
            const x = 0
            const y = 1
            // 当前标题中心Y轴值
            const currentCenterY = y + lineHeight / 2
            const titlefill = '#fff'
            const iconfill = '#2473ef'
            const lingstroke = '#2473ef'
            // 最后一个标题右侧X轴值
            let lastTitleRightX = 0
            mapList.value.forEach((item, index, arr) => {
                // 如果是第一项，前面就是0个字符，其他就是前一项字符长度的数值与当前项字符长度累加
                frontCharLengthArr.push(index === 0 ? 0 : frontCharLengthArr[index - 1] + arr[index - 1].name.length)
                // 当前标题宽度 = 字体大小 * 当前项字符长度 + 左右边距
                const currentTitleWidth = fontSize * item.name.length + titleLeftRigthPadding * 2
                // 当前标题中心X轴值 = 第一个标题左侧x值 + (icon宽度 + 左右边距) * 当前标题序号 + 字体大小 * 当前标题前面字符总数 + 当前标题宽度 / 2
                const titleCenterX =
                    x + (iconWidth + titleLeftRigthPadding * 2) * index + fontSize * frontCharLengthArr[index] + currentTitleWidth / 2
                // 当前标题前面图标中心X轴值
                const iconCenterX = titleCenterX - currentTitleWidth / 2 - iconWidth / 2
                if (index === arr.length - 1) {
                    // 总长度 = 最后一个标题左侧中心X值 + 最后一个标题宽度 / 2
                    lastTitleRightX = titleCenterX + currentTitleWidth / 2
                }
                const icon = {
                    type: 'text',
                    style: {
                        text: '>',
                        align: 'center',
                        verticalAlign: 'middle',
                        x: iconCenterX,
                        y: currentCenterY,
                        width: iconWidth,
                        height: lineHeight,
                        lineHeight,
                        fontSize,
                        fontWeight: 'bold',
                        fill: iconfill,
                        textShadowBlur: 20,
                        textShadowColor: '#fff',
                    },
                }
                const title = {
                    type: 'text',
                    style: {
                        text: item.name,
                        align: 'center',
                        verticalAlign: 'middle',
                        x: titleCenterX,
                        y: currentCenterY,
                        width: currentTitleWidth,
                        height: lineHeight,
                        lineHeight,
                        fontSize,
                        fontWeight: 'bold',
                        fill: titlefill,
                        textShadowBlur: 20,
                        textShadowColor: '#fff',
                    },
                    onclick: () => clickBreadcrumbsHandle(name, item.adcode),
                }
                group.push(index !== 0 ? { type: 'group', children: [icon, title] } : { type: 'group', children: [title] })
            })
            group.push({
                type: 'group',
                children: [
                    {
                        type: 'line',
                        shape: { x1: x, y1: y, x2: lastTitleRightX, y2: y },
                        style: { lineWidth, stroke: lingstroke },
                    },
                    {
                        type: 'line',
                        shape: { x1: x, y1: lineHeight + y, x2: lastTitleRightX, y2: lineHeight + y },
                        style: { lineWidth, stroke: lingstroke },
                    },
                ],
            })
            return group
        })(),
        toolbox: {
            show: true,
            orient: 'vertical',
            left: 'right',
            top: 'top',
            feature: { restore: { title: '复位' } },
        },
        tooltip: {
            trigger: 'item',
            backgroundColor: '#173b7c',
            borderWidth: 0,
            padding: 0,
            formatter: (params: any) => {
                // 自定义鼠标放入样式
                const one = (Math.random() * 100).toFixed(2)
                const two = (Math.random() * 100).toFixed(2)
                let regionName = '省份'
                switch (params.data.level) {
                    case 'province':
                        regionName = '省份'
                        break
                    case 'city':
                        regionName = '城市'
                        break
                    case 'district':
                        regionName = '区域'
                        break
                    default:
                        break
                }

                return `
                <ul style="width: 300px; height: 120px; font-size: 18px; color:#fff">
                    <li style="height: 40px; border: 1px solid #2473ef; display: flex; justify-content: flex-start; align-items: center">
                        <span style="width: 80px; text-align: center; line-height: 40px; border-right: 1px solid #2473ef">${regionName}</span>
                        <span style="width: 220px; text-align: center; line-height: 40px">${params?.name}</span>
                    </li>
                    <li style="height: 40px; border: 1px solid #2473ef; border-top: none; display: flex; justify-content: flex-start; align-items: center">
                        <span style="width: 80px; text-align: center; line-height: 40px; border-right: 1px solid #2473ef">上行</span>
                        <span style="width: 220px; text-align: center; line-height: 40px">${one}%</span>
                    </li>
                    <li style="height: 40px; border: 1px solid #2473ef; border-top: none; display: flex; justify-content: flex-start; align-items: center">
                        <span style="width: 80px; text-align: center; line-height: 40px; border-right: 1px solid #2473ef">下行</span>
                        <span style="width: 220px; text-align: center; line-height: 40px">${two}%</span>
                    </li>
                </ul>
            `
            },
        },
        geo: [
            {
                map: name, // 中国地图
                roam: true, // 鼠标缩放的效果
                left: '10%',
                top: '15%',
                right: '10%',
                bottom: '10%',
                zoom: 1.2,
                regions: getRandomRegionsData(mapdata),
                itemStyle: {
                    areaColor: { image: new URL('../../../images/map-bg.png', import.meta.url).href },
                    borderWidth: 1,
                    borderColor: '#176dfb',
                    shadowBlur: 5,
                    shadowColor: '#8eb9ff',
                },
                label: {
                    show: true,
                    color: '#fff',
                    distance: 30,
                    fontSize: 10,
                },
                emphasis: {
                    label: { show: true, fontSize: 20, fontWeight: 'bold', color: '#2473ef' },
                    itemStyle: { areaColor: '#a800ff' },
                },
            },
        ],
        series: [
            // 线条
            {
                tooltip: { show: false },
                type: 'lines',
                coordinateSystem: 'geo',
                lineStyle: { color: '#fffc03', width: 1, curveness: 0.2 },
                //开启动画特效
                effect: {
                    show: true,
                    period: 5, // 周期
                    roundTrip: true, // 往返
                    // trailLength: 0.7, // 尾迹长度
                    symbol: planePath,
                    color: '#fffc03',
                    symbolSize: 15,
                },
                data: mapdata[0].level !== 'province' ? [] : getRandomLineData(mapdata),
            },
            // 气泡标记
            {
                name: '点',
                type: 'scatter',
                coordinateSystem: 'geo',
                symbol: 'pin', //气泡
                symbolSize: 50,
                label: { show: true, formatter: '{b}', color: '#fff', fontSize: 12 },
                itemStyle: { color: '#F62157' },
                data: mapdata[0].level !== 'city' ? [] : getRandomPointData(mapdata),
            },
            // 涟漪扩展效果
            {
                type: 'effectScatter',
                coordinateSystem: 'geo',
                symbolSize: 10,
                rippleEffect: {
                    //坐标点动画
                    period: 3,
                    scale: 10,
                    brushType: 'fill',
                },
                label: {
                    show: true,
                    position: 'right',
                    formatter: '{b}',
                    color: '#56E0FF',
                    fontWeight: 'bold',
                    fontSize: 18,
                },
                itemStyle: {
                    color: (params) => {
                        switch (params.dataIndex) {
                            case 0:
                                return '#FF4763'
                            case 1:
                                return '#D880FF'
                            case 2:
                                return '#FFC447'
                            default:
                                return '#56E0FF'
                        }
                    },
                },
                data: mapdata[0].level !== 'district' ? [] : getRandomPointData(mapdata),
            },
            // 地图
            {
                type: 'map',
                map: name,
                geoIndex: 0,
                data: mapdata,
            },
        ],
    }
    echartRef.value?.setOption(option, { notMerge: true })
}
</script>

<style lang="scss" scoped></style>
